#!/usr/bin/env ruby
# frozen_string_literal: true

# filter-xed-find-underaccept: find inputs that XED potentially underaccepts
# (i.e., inputs the other high-quality decoders think are valid)

require "json"

# TODO(ww): Remove this.
BDDISASM_SO = "./src/worker/bddisasm/bddisasm.so"
XED_SO = "./src/worker/xed/xed.so"
ZYDIS_SO = "./src/worker/zydis/zydis.so"
ICED_SO = "./src/worker/iced/iced.so"

def success?(decoder)
  decoder[:status][:value] == 1
end

def failure?(decoder)
  !success?(decoder)
end

def success_by_consensus?(*decoders)
  nsuccesses = decoders.select { |d| success?(d) }.size

  (nsuccesses / decoders.size.to_f) > 0.50
end

warn "[+] pass: filter-xed-find-underaccept"

count = 0
$stdin.each_line do |line|
  result = JSON.parse line, symbolize_names: true

  bddisasm = result[:outputs].find { |o| o[:worker_so] == BDDISASM_SO }
  xed = result[:outputs].find { |o| o[:worker_so] == XED_SO }
  zydis = result[:outputs].find { |o| o[:worker_so] == ZYDIS_SO }
  iced = result[:outputs].find { |o| o[:worker_so] == ICED_SO }

  # If XED reports failure when other high-quality decoders don't, keep it.
  $stdout.puts result.to_json if failure?(xed) && success_by_consensus?(bddisasm, zydis, iced)

  count += 1
end

warn "[+] pass: filter-xed-find-underaccept done: #{count} filtered"
